package smtp;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;

import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * Screen where the user will be able to type and send a message
 * @author wendlandts, chandlerr, liw
 *
 */
public class MessageScreen extends JFrame {

	private JButton send = new JButton("Send");
	private JButton attach = new JButton("Attach a file");
	private JButton removeAll = new JButton("Remove All Attached Files");
	private JLabel sender = new JLabel();
	private JTextField toField = new JTextField();
	private JTextField subjectField = new JTextField();
	private JTextArea messageArea = new JTextArea("Type your message here. . .");
	private JScrollPane messageAreaScroll = new JScrollPane(messageArea);
	private JPanel attachmentPanel;
	private boolean fileAttached = false;
	private File[] attachedFiles = new File[0];
	private boolean gainedFocus = false;
	private Session session=null;

	/**
	 * If the ReceivedEmailParser is not null, then it will construct a message screen
	 * with the given values in the given mail
	 * If it is null, then it will create a blank message screen
	 * @param mail The message that this screen will be based off of
	 * @param session The current session in use
	 * @param focus True if it is a reply/forward message. Used to stop the content area from deleting itself
	 */
	public MessageScreen(ReceivedEmailParser mail, Session session, boolean focus) {
		if(mail != null) {
			gainedFocus = focus;
			toField.setText(mail.getReplayToString());
			subjectField.setText(mail.getSubject());
			messageArea.setText(mail.getContent());

			// If the file is forwarded, it won't have a RE: in front of the subject
			// And when forwarding, you don't want the to field filled with ppl
			if(!subjectField.getText().equals("")) {
				if(!subjectField.getText().substring(0, 3).equalsIgnoreCase("RE:")) {
					toField.setText("");
				}
			}
		}
		sender.setText(session.getProperties().getProperty("user"));
		this.session = session;
		setUpUI();
	}

	/**
	 * Method used to initially set up the frame 
	 */
	public void setUpUI() {
		this.setSize(750, 500);
		this.setLayout(new BorderLayout());
		this.setTitle("Compose a Message");

		// Set up the top part of the frame
		JPanel mainTopPanel = new JPanel();
		mainTopPanel.setLayout(new GridLayout(1,1));

		// Set up the top BorderLayout
		JPanel topBorder = new JPanel();
		topBorder.setLayout(new BorderLayout());
		// Make a panel for the attachments on the bottom of this border
		attachmentPanel = new JPanel();
		attachmentPanel.setLayout(new FlowLayout());
		attachmentPanel.add(new JLabel("Attached: "));

		// Add it to the border panel
		topBorder.add(attachmentPanel, BorderLayout.SOUTH);

		// Add listeners to the buttons and the Text Area
		messageArea.addFocusListener(new AreaFocusListener());	
		ButtonListener listener = new ButtonListener();
		send.addActionListener(listener);
		attach.addActionListener(listener);
		removeAll.addActionListener(listener);

		// Add a GridLayout to the left side of the top for specific fields
		JPanel upperLeftPanel = new JPanel();
		upperLeftPanel.setLayout(new GridLayout(3,2));
		upperLeftPanel.add(new JLabel("From: "));
		upperLeftPanel.add(sender);
		upperLeftPanel.add(new JLabel("To: "));
		upperLeftPanel.add(toField);
		upperLeftPanel.add(new JLabel("Subject: "));
		upperLeftPanel.add(subjectField);

		// Add a GridLayout to the right side of the top for the send button and attachment button
		JPanel upperRightPanel = new JPanel();
		upperRightPanel.setLayout(new GridLayout(3,1));
		upperRightPanel.add(send);
		upperRightPanel.add(removeAll);
		upperRightPanel.add(attach);

		// Add the panels to the main top panel
		mainTopPanel.add(upperLeftPanel);
		mainTopPanel.add(upperRightPanel);

		// Add the main panel to the Center of the top border
		topBorder.add(mainTopPanel, BorderLayout.CENTER);

		//Add the panel to the main body
		this.add(topBorder, BorderLayout.NORTH);
		this.add(messageAreaScroll, BorderLayout.CENTER);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.setVisible(true);
	}

	/**
	 * Sends the components of the message to a message class to be assembled into a message ready to be sent. 
	 * Also differentiates between having an attachment or not
	 * @throws AddressException 
	 */
	public void assembleMessage() throws AddressException {
		boolean cont = false;
		NewEmail mail = new NewEmail(session);

		// Always check to see if the current step succeeded 
		InternetAddress from = new InternetAddress();
		from.setAddress(sender.getText());
		cont = mail.setAddresses(from,gatherRecip(), null, null);
		if(cont){
			if(fileAttached){
				mail.setAttachments(attachedFiles);
			}
			cont = mail.setSubject(subjectField.getText());
			if(cont) {
				cont = mail.setText(messageArea.getText(), "US-ASCII");
				if(cont) {
					cont = mail.send("smtp");
					if(!cont) {
						JOptionPane.showMessageDialog(null,mail.getError());
					}
				} else {
					JOptionPane.showMessageDialog(null,mail.getError());
				}
			} else {
				JOptionPane.showMessageDialog(null,mail.getError());
			}
		} else {
			JOptionPane.showMessageDialog(null,mail.getError());
		}

		if(cont) {
			JOptionPane.showMessageDialog(this, "Message sent sucessfully!");
			this.dispose();
		} 
	}

	/**
	 * Gathers the specified recipients of the message to an Array
	 * @throws AddressException 
	 */
	public InternetAddress[] gatherRecip() throws AddressException {
		// Then add them to an Array of InternetAddress
		InternetAddress[] addresses = null;
		String recipString = toField.getText();
		if(recipString.contains(";")) {
			String[] tokens = recipString.split(";");
			addresses = new InternetAddress[tokens.length];
			if(tokens.length != 0) {
				int i = 0;
				for(String s : tokens) {
					addresses[i] = new InternetAddress(s, true);
					i++;
				}
			} else {
				throw new AddressException();
			}
		} else {
			addresses = new InternetAddress[1];
			addresses[0] = new InternetAddress(toField.getText(), true);
		}
		return addresses;
	}
	/**
	 * Removes all the currently attached files
	 */
	public void removeAllAttachments() {
		fileAttached = false;
		attachedFiles = new File[0];
		attachmentPanel.removeAll();
		attachmentPanel.add(new JLabel("Attached: "));
		this.validate();
	}

	/**
	 * Prompts the user to select a file to attach
	 * If the file is valid, make note that there is now an attachment on the email
	 */
	public void attachFile() {
		File chosenFile;
		JFileChooser chooser = new JFileChooser();

		int retVal = chooser.showOpenDialog(MessageScreen.this);
		if(retVal == JFileChooser.APPROVE_OPTION) {
			chosenFile = chooser.getSelectedFile();

			// Check to make sure the file exists
			if(chosenFile.exists()) {
				// Increase the size of the array by one and add the new file
				File[] previousArray = attachedFiles;
				attachedFiles = new File[attachedFiles.length + 1];

				int i = 0;
				for(File x : previousArray) {
					attachedFiles[i] = x;
					i++;
				}
				attachedFiles[attachedFiles.length - 1] = chosenFile;

				attachmentPanel.add(new JLabel(chosenFile.getName()));
				this.validate();
				fileAttached = true;
			} else {
				JOptionPane.showMessageDialog(MessageScreen.this, "The file does not exist!");
			}
		}
	}

	/**
	 * Listens to the MessageArea for focus
	 * Once gained, it will delete the starting message 
	 * Making room for the user to type their message
	 * @author wendlandts
	 */
	private class AreaFocusListener implements FocusListener {
		@Override
		public void focusGained(FocusEvent arg0) {
			if(!gainedFocus) {
				messageArea.setText("");
				gainedFocus = true;
			}
		}

		@Override
		public void focusLost(FocusEvent arg0) {
			// Do nothing
		}
	}

	/**
	 * This ActionListener will listen to the send and attach buttons 
	 * When the send button is hit, it will assemble the current message 
	 * When the attach button is hit, the user will be prompted to select a file
	 * @author wendlandts
	 */
	private class ButtonListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if(e.getSource() == send) {
				try {
					assembleMessage();
				} catch (AddressException e1) {
					JOptionPane.showMessageDialog(MessageScreen.this, "Invalid recipients: check format");
				}
			} else if(e.getSource() == attach) {
				attachFile();
			} else {
				removeAllAttachments();
			}
		}
	}
}
